之前為方便快速了解我們程式完整的功能,
所以把所有的資料都放在Controller裡面。
今天這篇我們來整理一下先前的程式碼,
順便帶大家瞭解一下MVC-Model的功用。
這是一隻在專案創建時就會有的文件,
在這文件中會存放一些關於系統中的設定。
我們也會在這新增一些系統參數在這邊,供我們系統運行的時候使用。
"WebmenuConnectionString":"Server=.\\SQLEXPRESS;Initial Catalog=WebMenu;user id=webmenu;password=xxxxxxxx;Integrated Security=False"
(帳號密碼用自己當初在資料庫設定的密碼)
3.開啟 HomeController.cs
4.在 建構子時透過 DI 注入 IConfiguration
private IConfiguration _config;
public HomeController(ILogger<HomeController> logger, IConfiguration config)
{
_logger = logger;
_config = config;
}
因為在ASP.NET Core 中一開始執行Startup.cs
的時候,
就會透過 DI 注入 IConfiguration 組態設定檔內容。
所以我們在撰寫的時候不需要去注意修改Startup.cs
大家實際運用MVC開發的時候,或多或少都有一些功能分類上的差異。
那這邊對Model處理的業務範圍,用處理資料的地方 簡言概括之,
不管是傳送、接收、或是對資料的運算,我們都會放在Model裡面。
我們這邊分類的方式也很簡單,就是一個畫面配上一個Model,
用來處理data的傳送、接收、運算。
這邊放一些通用的資料處理function()
Common.cs
public static string Obj2JsonString(object obj)
{
return JsonConvert.SerializeObject(obj);
}
CustomerModel.cs
public class Customer
{
public static CustomerModel customer
{
get
{
if (mCustomer == null)
{
mCustomer = new CustomerModel();
}
return mCustomer;
}
}
這樣的設計方式可以保證只創建單一物件,
並且在系統剛啟動時不直接創建物件,也能加快系統的加載速度。
(不過這邊沒有特別處理異步的問題,有興趣的小夥伴在自行改寫)
public List<Menu> SelectMenu(IConfiguration config)
{
//連線設定
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
//連線字串
ConnectionString = config.GetValue<string>("WebmenuConnectionString"),
DbType = DbType.SqlServer,//連線類型
IsAutoCloseConnection = true //自動關閉連線
});
//當執行時,觸發事件
db.Aop.OnLogExecuting = (sql, pars) =>
{
Console.WriteLine(sql);//查看SQL語法
};
var list = db.Queryable<Menu>().ToList();
foreach (var menu in list)
{
menu.Item = menu.Item.Trim();
Console.WriteLine(menu.Item);
}
return list;
}
public void CreateOrder(string data, string phone,out Dictionary<string, Menulistb> order_body,out Menulisth order_head)
{
order_head = new Menulisth()
{
Formnum = phone
};
order_body = JsonConvert.DeserializeObject<Dictionary<string, Menulistb>>(data);
}
public bool insertOrder(IConfiguration config ,Dictionary<string, Menulistb> order_body, Menulisth order_head)
{
//連線設定
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = config.GetValue<string>("WebmenuConnectionString"),
DbType = DbType.SqlServer,//連線類型
IsAutoCloseConnection = true //自動關閉連線
});
try
{
//當執行時,觸發事件
db.Aop.OnLogExecuting = (sql, pars) =>
{
Console.WriteLine(sql);//查看SQL語法
};
db.BeginTran();
//寫入表頭 並 回傳表頭資料
order_head = db.Insertable(order_head).ExecuteReturnEntity();
//逐筆將表身資料寫入
foreach (var keyvalue in order_body)
{
var item = keyvalue.Value;
item.H_uid = order_head.Uid;
db.Insertable(item).ExecuteCommand();
}
db.CommitTran();
}
catch
{
db.RollbackTran();//rollback
throw;
}
return true;
}
我們將處理資料的業務轉道model之後,
我們的HomeController.cs
不僅瘦身成功,
可讀性也是大幅度上升。
HomeController.cs 裡的Customer():
public IActionResult Customer()
{
var customer = CustomerModel.customer;
var menu_list = customer.SelectMenu(_config);
string jsonData = Common.Obj2JsonString(menu_list);
ViewBag.menuData = jsonData;
return View();
}
這樣我們就可以非常清晰的看懂程式碼中做的事情:
HomeController.cs 裡的CreateOrder():
public ActionResult CreateOrder(string data,string phone)
{
var customer = CustomerModel.customer;
customer.CreateOrder(data, phone, out var order_body,out var order_head);
customer.insertOrder(_config,order_body, order_head);
return Ok();
}
當專案開發到一定程度的時候,適時的回頭去做Code Review是件非常重要的事情。
不然常常專案開發到後面會變得殘破不堪東貼西補的。
一般在外面使用MVC開發時,很常可以看見這種
1個View + 1個Controller + 1個 model的方式
這樣的配置雖然不一定是效率比較好的配置方式,
但在專案中檢索時就相對的方便許多。
有些人在看到
public static string Obj2JsonString(object obj)
{
return JsonConvert.SerializeObject(obj);
}
會有些疑惑,為什麼要把別人包好的功能在包一層起來?
這樣做主要可以讓Controller與套件解耦合,
當我們要對套件進行更新或是對某些功能做異動的時候,
我們只需要到Model上面進行維護,而不需要連Controller一起更動。
可能有些萌新還會問為什麼不把config直接存在model裡面使用,
這樣不就不需要一直傳參數了嗎?
(設計成 function()
與 function(arg1,arg2)
的區別)
當然,這種設計方式是完全沒問題的。
只是這樣的設計方式我們在閱讀程式碼的時候,
會比較難找到資料的流向。
比較簡單的分法就是:
function()
就存參數在Class內(private、protected)function(arg)
就用傳參數的方式(public、default)簡單版:
有細心的小夥伴應該會發現,我之前menu 跟 order 傻傻分不清楚,
導致命名的時候有一點奇怪。因為不影響功能,所以就將就一下吧。